def list_assignment():
    """
    列表是可变数据类型
    简单赋值会使其指向同一块空间，所以修改列表元素会相互影响
    """
    a = [1, 2, 3]
    b = a
    print(a)  # [1, 2, 3]
    print(b)  # [1, 2, 3]
    print(f"a的地址{id(a)}")  # a的地址2157846974848
    print(f"b的地址{id(b)}")  # b的地址2157846974848
    b[0] = 10
    print(a)  # [1, 2, 3]
    print(b)  # [10, 2, 3]
    print(f"a的地址{id(a)}")
    print(f"b的地址{id(b)}")


def use_copy_simple():
    """
    使用列表自身的copy,开辟新空间存储
    因为地址不同，所以修改列表元素不会相互影响
    """
    a = [1, 2, 3]
    b = a.copy()
    print(a)  # [1, 2, 3]
    print(b)  # [1, 2, 3]
    print(f"a的地址{id(a)}")  # a的地址2270348628352
    print(f"b的地址{id(b)}")  # b的地址2270348630208
    b[0] = 10
    print(a)  # [1, 2, 3]
    print(b)  # [10, 2, 3]
    print(f"a的地址{id(a)}")
    print(f"b的地址{id(b)}")


import copy


def use_shallow_copy_one():
    """
    浅拷贝，复制了一个副本，指向不同空间，所以修改列表元素不会相互影响
    """
    a = [1, 2, 3]
    b = copy.copy(a)
    print(a)  # [1, 2, 3]
    print(b)  # [1, 2, 3]
    print(f"a的地址{id(a)}")  # a的地址1673386121408
    print(f"b的地址{id(b)}")  # b的地址1673386119552
    b[0] = 10
    print(a)  # [1, 2, 3]
    print(b)  # [10, 2, 3]
    print(f"a的地址{id(a)}")
    print(f"b的地址{id(b)}")


def use_shallow_copy_two():
    """
    c和d的元素类型是列表，所以c和d存储是其指向列表的地址
    所以进行浅拷贝时，仅仅在不同地址存储相同的列表引用地址，但其指向的是同一个列表
    即只进行了一层拷贝，不会进行更深层的拷贝
    """
    a = [1, 2, 3]
    b = [4, 5, 6]
    c = [a, b]
    d = copy.copy(c)
    print(c)  # [[1, 2, 3], [4, 5, 6]]
    print(d)  # [[1, 2, 3], [4, 5, 6]]
    print(f"c的地址{id(c)}")  # c的地址1164275133952
    print(f"d的地址{id(d)}")  # d的地址1164274122176
    a[0] = 10
    print(c)  # [[10, 2, 3], [4, 5, 6]]
    print(d)  # [[10, 2, 3], [4, 5, 6]]
    print(f"c的地址{id(c)}")  # c的地址1164275133952
    print(f"d的地址{id(d)}")  # d的地址1164274122176
    print(id(c[0]), id(d[0]))  # 1164271409344 1164271409344
    print(id(c[1]), id(d[1]))  # 1164271407488 1164271407488


def use_deep_copy():
    """
    深拷贝：对每一层都进行拷贝，即每一层都指向不同的地址空间
    """
    a = [1, 2, 3]
    b = [4, 5, 6]
    c = [a, b]
    d = copy.deepcopy(c)
    print(c)  # [[1, 2, 3], [4, 5, 6]]
    print(d)  # [[1, 2, 3], [4, 5, 6]]
    print(f"c的地址{id(c)}")  # c的地址2086638813888
    print(f"d的地址{id(d)}")  # d的地址1164274122176
    a[0] = 10
    print(c)  # [[10, 2, 3], [4, 5, 6]]
    print(d)  # [[1, 2, 3], [4, 5, 6]]
    print(f"c的地址{id(c)}")  # c的地址2086638813888
    print(f"d的地址{id(d)}")  # d的地址2086637813248
    print(id(c[0]), id(d[0]))  # 2086635100352 2086637734784
    print(id(c[1]), id(d[1]))  # 2086635098496 2086635437056


class Hero:
    def __init__(self, name, blood):
        self.name = name
        self.blood = blood
        self.equipment_list = ['血包', '激素']

    def __str__(self):
        return f"{self.name},血量{self.blood},装备{self.equipment_list}"


def use_deep_copy_obj():
    old_hero = Hero("猎空", 150)
    new_hero = copy.deepcopy(old_hero)
    new_hero.equipment_list.append("护盾")
    new_hero.blood = 100  # 新对象修改后，原对象不会受到任何影响
    print(old_hero)
    print(new_hero)


if __name__ == '__main__':
    # list_assignment()
    # use_copy_simple()
    # use_shallow_copy_one()
    # use_shallow_copy_two()
    # use_deep_copy()
    use_deep_copy_obj()
